Advanced Design Methods¶
In this lecture part, we will present a few important concepts involved when designing real-life circuits, and introduce some advanced concepts related to simulation or system design.
It is meant as a collection of useful subjects, it will be improved during the semester.
Clock Domain Crossing¶
Multiple Clock domain contraining as been presented in the constraint section of the synthesis chapter.
The main issue with clock domain crossing is that clock phases are typically unknown or uncertain. Consequentely, the setup and hold checks cannnot be properly ensured when sampling a logic output with a clock different than the producing clock, hence we cannot be sure of the result.
Single Bit Metastability¶
This problem is commonly know as metastability, and means that the value of the sampled bit could be instable for a certain time. Thus the logic could toggle between 1 and 0 in a undefined manner, causing unexpected states of logic.
The explanation from wikipedia is good enough for now:
https://en.wikipedia.org/wiki/Metastability_in_electronics
The solution to avoid metastability is to introduce a delay by using a shift register. Because the energy of a metastable signal will tend towards 0 or 1, each register sampling stage increases the probability that the signal will be sampled out of the metasability region and have a clear defined value.

Picture extracted from wikipedia https://en.wikipedia.org/wiki/Metastability_in_electronics
Wide Bus Crossing using a FIFO¶
The register delay is thus a simple option for a clean crossing of a single bit, however things can get more complicated for multiple bits. Indeed, a wide bus will be physically scattered over an area.

The clock to data relationship will therefore be very different for every signal, and the chances of delayed arrival increase.

Solving this issue would require a proper setup synchronisation signals, which can be used to signal the logic that all bits are safely available, but this could grow quite complex because such signals typically go both ways:
- The data consumer needs to know when data is valid.
- The data producer needs to know it the consumer is too busy to get new data.
If the data width increases, the design would anyway require to use some memory to store the data, hence requiring the use of a synchronised memory.
Such a memory is typically implemented using an asynchronous First-in First-out block. ASYNC Fifos rely mostely on a RAM memory, because these usually are implemented with separated clocks for reading and writing.
The control signals to write data and check the status are then careful synchronised and some extra logic is added to handle the corner cases covering the synchronisation time between the two clocks.

Oversimplified ASYNC Fifo overview
The idea behind a FIFO and an ASYNC fifo is easy to understand, although a totally bug-free realisation can be hard to reach. On the shown picture, on can imagine that a wrong synchronisation could give one side the information that data is present, although not already written.
Hint
Usually the ASYNC FIFO blocks can be found ready to use as open source components, or generated using some vendor tool on FPGA platforms.
State Machines¶
State machines are keys to most circuits. You may have noticed when describing the counter in the Übung, but the counter you wrote could be described with states.
For example, when the counter is counting, you could write “Counting state”, after the overflow comes, “Overflow State”, and if not overflow clear came, the next overflow puts the counter in an error status.
A state machine is usually easy to describe, you need:
- A register holding the value of the state: 0,1,2,3 etc..
- A condition processing based on inputs and actual state to update the state value (if … begin state <= next_state; … end)
- The state’s value bits can be mapped to outputs to control other parts of the design directely, typically:
- Start
- Stop
- Reset etc…
The documented description of a state machine is simply a drawing, of which kind you have seen before, like the following:
If we are lucky, we will find a graphical tool to description your FSM and generate the hardware.
FSMDesigner¶
One of these tools is called FSMDesigner from the University of Heidelberg. It is a Graphical Program which generates verilog based on states and transition definitions.

It’s usage is quite easy and helps perfectely define the cases that leads in and out of states. In FSMDesigner, you will need to define:
- Inputs like on a verilog module
- Outputs like on a verilog module
- States
- For each state, the values for the outputs. Each State must have a unique value and assigned by hand.
- If you have more states than outputs, you will need “dummy” outputs to code all the states uniquely
- Transitions from states to other
- Each transition can have multiple condition
- A condition is the input values, for which the state will change to the target states
- For each state, condition values must be uniquely defined
Once an FSM is correctely defined, the Tool can generate a verilog module, with the correct content, like this one:
- A state value register
- Condition to change register
- Each bit of the state value is used to drive the design
module counter_fsm (
input wire clk,
input wire res_n,
// Inputs
//------------
input wire enable,
input wire last_value,
input wire reinit,
input wire clear_overflow,
// Outputs
//------------
output wire overflow,
output wire counting,
output wire idle
);
...
always @(*) begin
casex({inputvector, current_state})
...
{4'bxxx1, IDLE}: next_state = IDLE;
{4'b1x00, IDLE}: next_state = COUNT;
....
endcase
end
...
endmodule
Code Coverage¶
The FSMDesigner code generator provides a good example for Coverage generation.
Coverages are Special Simulator instructions, which allows the “count” the number of occurences of a register value. In the case of an FSM, a coverage would count every value of the state register, hence the actual state, and produce a report.
The coverage reports for State Machines are very interesting, because we can detect states which have never been visited, and make deductions:
- Is the testbench missing a test case?
- Is there a bug in the design for the State never to be used?
- The State is maybe useless and can be removed.
Hint
Coverages are not really a topic here but we will try to use them during the practical work
Demonstrator¶
To demonstrate a few more advanced concepts and options to design a system and simulate it, it is a good Idea to try to work with a little system.
We have used the simple counter to show most of the low-level concepts involved during the design phase, like timing analysis, reset choice, clock gating etc… An idea for a system involving more than a counter, that would cover hardware design and software integration, would be to integrate a few instances of these counters in a processor environment, like a microcontroller.
There are many available options to use a microprocessor in a design, for example the openRISC from opencores or the SPARC Leon processor from Gaisler Aerospace.
Architecture Idea¶
This is the Big Picture of what can be reached. Most of the design parts are overly simplified, but are kept in a small number of source files, which should make them easy to study.

Global overview of system components
BETTER DESCRIPTION OF COMPONENTS INTERACTION
Counter with FSM Designer¶
Hint
FSMDesigner installation for windows MSYS2 here
The counter was build using the FSM Designer:
- FSM Designer project demos/counter_system/hw/counter/counter.pro.xml
- Generated FSM code: demos/counter_system/hw/counter/counter_fsm.v
- Counter implementation using the FSM: demos/counter_system/hw/counter/counter.v
Microcode Stream Engine¶
Hint
Source file: demos/counter_system/hw/system/counter_system.v
Using an existing processor or creating one ourselves could be a bit too much work or challenging, considering we want to keep a simple system to properly understand.
Basically, the simplest definition of a microprocessor we can give, is that it is a circuit that interprets instructions one after each other.
Real-Life microprocessors are quite complex because they interact with a lot of sub components, and optimised for speed or power consumption, but if we just focus on implementing a few instructions to interact with the counters, it should be easy enough.
The key components are:
- 32 bits width, because counters are 32 bits
- Single instruction stream
- One cycle per instruction -> easy to design
- An Instruction can have one data QWORD following
- Instructions types:
- Store to memory
- Load from memory
- Bit Manipulation
- Right/Left Bit Shift
- Force bit to 1/0
- Special Instruction (useless?):
- Force reset of components around the engine
- Release resets
- No Operation (NOOP), just wait for a cycle
- Memory Mapping:
- First addresses to explicit control registers
- RAM addresses to generic memory
This architecture is very simplistic, but avoids generic interfaces to external devices or memories, making the design easier. The single cycle architecture also makes the code easy to write, as no intruction processing states are required.
Assembly compiler¶
Hint
Example file app/src/main/scala/kit/ipe/adl/dds/demo/compiler/ExamplePrograms.scala
- Transforms “explicit” lines of instructions, to the actual 32bit instruction(s) code(s)
- Save to a file to be read by the testbench
Simulator GUI Integration¶
- Uses a VPI Module to launch a Java program and connect simulator VPI functions
- The java program offers a little gui to watch Counter state machines
- The compiler can be called to generate a new set of instructions
- A value can be written to the testbench to update the instructions array
Simulator Integration using VPI¶
Reference for code used in the Demonstrator
VPI is part of the verilog standard
VPI and Java Interface¶
Extra: Parsing Library file¶
TBD